package com.nexus.all.service.impl;

import cn.hutool.core.util.XmlUtil;
import com.nexus.all.manager.AiChooseManager;
import com.nexus.all.manager.UserManager;
import com.nexus.all.model.AiChoose;
import com.nexus.all.service.AiService;
import com.nexus.all.service.WechatService;
import com.nexus.all.utils.wxUtils.AesException;
import com.nexus.all.utils.wxUtils.WXBizMsgCrypt;
import com.nexus.all.utils.wxUtils.WechatUtil;
import com.nexus.all.utils.wxUtils.WxTextMsgBean;
import com.nexus.bean.exeption.ServiceException;
import com.nexus.bean.result.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;

@Slf4j
@Service
public class WechatServiceImpl implements WechatService {


    private final UserManager userManager;
    private final AiChooseManager aiChooseManager;
    private final AiService aiService;

    @Autowired
    public WechatServiceImpl(UserManager userManager, AiChooseManager aiChooseManager, AiService aiService) {
        this.userManager = userManager;
        this.aiChooseManager = aiChooseManager;
        this.aiService = aiService;
    }

    @Value("${wechat.token:}")
    private String token;
    @Value("${wechat.appId:}")
    private String wxAppId;

    @Value("${wechat.encodingAesKey:}")
    private String encodingAesKey;

    private static Set<String> expireKey = new HashSet();

    @Override
    public String getEventInfo(String signature, String timestamp, String nonce, String echostr) {
        log.info("微信回调过来消息：{}", echostr);
        if (!checkSign(signature, timestamp, nonce)) {
            log.info("非微信回调访问，接口请求失败");
            throw new ServiceException(ResultCode.COMMON_MESSAGE, "非微信访问，接口请求失败");
        }
        return echostr;
    }

    @Override
    public String getBackInfo(String xml, String msgSignature, String signature, String timestamp, String nonce) {
        //1.先验证是否为微信请求回调
        log.info("微信回调过来的数据：{},signature={},timestamp{},nonce={}", xml, signature, timestamp, nonce);
        if (!checkSign(signature, timestamp, nonce)) {
            log.info("非微信回调访问，接口请求失败");
            throw new ServiceException(ResultCode.COMMON_MESSAGE, "非微信访问，接口请求失败");
        }
        // 2、接收微信服务器推送的时间信息
        // 解密微信服务器推送消息并 对xml解析
        String xmlStr = "";
        try {
            WXBizMsgCrypt pc = new WXBizMsgCrypt(token, encodingAesKey, wxAppId);
            xmlStr = pc.decryptMsg(msgSignature, timestamp, nonce, xml);
            log.info("微信回调解密后的数据：{}", xmlStr);
        } catch (AesException e) {
            log.error("解密失败:{}", e);
        }
        Map<String, Object> resMap = XmlUtil.xmlToMap(xmlStr);
        log.info("微信回调解析xml数据为：{}", resMap);
        if (Objects.isNull(resMap.get("MsgType"))) {
            log.info("微信回调返回数据为空");
            throw new ServiceException(ResultCode.COMMON_MESSAGE, "微信回调返回数据为空");
        }
        //消息事件
        String messageEvent = String.valueOf(resMap.get("Event"));
        //发送方帐号（open_id）
        String fromUser = String.valueOf(resMap.get("FromUserName"));
        // 开发者微信号
        String toUser = String.valueOf(resMap.get("ToUserName"));
        // 即创建二维码时的二维码scene_id
        String eventKey = String.valueOf(resMap.get("EventKey"));
        // 消息创建时间 （整型）
        Long createTime = Long.valueOf(resMap.get("CreateTime") + "");

        String key = fromUser + "-" + toUser + "-" + createTime;
        // 重复通知不作处理
        if (expireKey.contains(key)) {
            log.info("重复通知了");
            return "success";
        } else {
            expireKey.add(key);
        }

        String msg = "";

        log.info("事件类型为：{}", messageEvent);
        switch (messageEvent) {
            case "subscribe":
                log.info("用户触发关注公众号事件推送：openid={}携带参数={}", fromUser, eventKey);
                eventKey = eventKey.replace("qrscene_", "");
                List<AiChoose> aiChooseList = aiChooseManager.getByLevel(0);
                StringBuilder builder = new StringBuilder();
                builder.append("绑定成功，请输入序号选择：");
                builder.append("\n");
                builder.append("序号\t\t\t选项");
                for (AiChoose aiChoose : aiChooseList) {
                    builder.append("\n");
                    builder.append(aiChoose.getId() + "\t\t\t" + aiChoose.getAiChoose());
                }
                msg = WxTextMsgBean.getInstance(fromUser, toUser, createTime, builder.toString()).toXml();
                break;
            case "SCAN":
                log.info("用户扫码触发已关注公众号事件推送：openid={}携带参数={}", fromUser, eventKey);
                //用户已关注公众号
                msg = WxTextMsgBean.getInstance(fromUser, toUser, createTime, "绑定成功").toXml();
                break;
            case "unsubscribe":
                log.info("用户扫码触发取消公众号事件推送：openid={}携带参数={}", fromUser, eventKey);
                /*merUserService.updateMerUserByOpenid(fromUser, WechatBindStatusEnum.REMOVE_BIND.getValue());*/
                break;
            default:
                String content = null;
                if (Objects.nonNull(resMap.get("Content"))) {
                    content = resMap.get("Content").toString();
                } else {
                    content = resMap.get("PicUrl").toString();
                }
                String str = aiService.autoReply(fromUser, content);
                msg = WxTextMsgBean.getInstance(fromUser, toUser, createTime, str).toXml();
                break;
        }

        log.info("回复信息 msg: {}", msg);
        return msg;
    }

    /**
     * 验证消息是否是微信服务器
     *
     * @return
     */
    public boolean checkSign(String signature, String timestamp, String nonce) {
        log.info("验证消息的确来自微信服务器 :本身{}", signature);
        log.info("验证消息的确来自微信服务器 :加密判断{}", WechatUtil.gen(token, timestamp, nonce));
        if (WechatUtil.gen(token, timestamp, nonce).equals(signature)) {
            return true;
        }
        return false;
    }
}
